package org.lex.net.telnet;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;

import org.lex.io.IO;
import org.lex.net.TCPClient;
import org.lex.net.uitl.NetUtilities;


public class TelnetClient extends TCPClient {
	public static final int DEFAULT_TELNET_PORT = 23;
	private Charset serverCharset = null;
	protected BufferedReader serverReader = null;
	private BufferedWriter serverWriter = null;

	// =============================
	// Constructors
	// =============================
	public TelnetClient() {
		super();
		this.serverCharset = Charset.defaultCharset();
	}

	// =============================
	// Instance Methods
	// =============================
	public Charset getServerCharset() {
		return this.serverCharset;
	}

	public void setServerCharset(Charset serverCharset) {
		this.serverCharset = serverCharset;
		// FIXME what about data cached in reader&writer??
		if (true == isServerOpen())
			this.createServerReaderAndWriter();
	}

	@Override
	public void closeServer() throws IOException {
		IO.flushQuietly(serverWriter);
		IO.closeQuietly(serverWriter);
		IO.closeQuietly(serverReader);
		this.serverReader = null;
		this.serverWriter = null;
		super.closeServer();
	}

	public void openServer(String host) throws UnknownHostException, IOException {
		this.openServer(InetAddress.getByName(host), DEFAULT_TELNET_PORT);
	}

	@Override
	public void openServer(String host, int port) throws UnknownHostException, IOException {
		this.openServer(InetAddress.getByName(host), port);
	}

	@Override
	public void openServer(InetAddress host, int port) throws IOException {
		super.openServer(host, port);
		this.createServerReaderAndWriter();
	}

	private void createServerReaderAndWriter() {
		this.serverReader = new BufferedReader(new InputStreamReader(getServerInputStream(), this.serverCharset));
		this.serverWriter = new BufferedWriter(new OutputStreamWriter(getServerOutputStream(), this.serverCharset));
	}

	public BufferedReader getServerReader() {
		return this.serverReader;
	}

	public BufferedWriter getServerWriter() {
		return this.serverWriter;
	}

	public void sendServer(CharSequence msg) throws IOException {
		serverWriter.append(msg);
		if (false == NetUtilities.isEndWithCRLF(msg))
			serverWriter.append(NetUtilities.CRLF);
		serverWriter.flush();
	}

	public void sendServer(char[] buf, int offset, int len) throws IOException {
		serverWriter.write(buf, offset, len);
		int end = offset + len - 1;
		if (end > 0 && (NetUtilities.LF != buf[end] || NetUtilities.CR != buf[end - 1]))
			serverWriter.append(NetUtilities.CRLF);
		serverWriter.flush();
	}
}
